﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Net;
using IGolovkine.AoA.Diagnostics;

namespace IGolovkine.AoA.Tcp
{
    public class TcpListener : IDisposable
    {
        private readonly Subject<TcpConnection> _connections;
        private readonly IDisposable _task;
        
        public TcpListener(int port) : this(IPAddress.Any, port)
        {
        }

        public TcpListener(IPAddress ipAddress, int port)
        {
            System.Net.Sockets.TcpListener listener = new System.Net.Sockets.TcpListener(ipAddress, port);
            listener.Start();

            _connections = new Subject<TcpConnection>();
            bool cancelPending = false;

            Task task = Task.Factory.StartNew(() =>
            {
                try
                {
                    while (cancelPending == false)
                    {
                        TcpClient client = listener.AcceptTcpClient();
                        TcpConnection tcpConnection = new TcpConnection(client);
                        _connections.OnNext(tcpConnection);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Connection listener on error: " + ex);
                    _connections.OnError(ex);
                }
                finally
                {
                    Console.WriteLine("Connection listener on completed");
                    _connections.OnCompleted();
                }
            });

            _task = Disposable.Create(() =>
            {
                cancelPending = true;
                listener.Stop();
                task.Wait();
            });
        }

        public IObservable<TcpConnection> Connections
        {
            get { return _connections; }
        }

        public void Dispose()
        {
            _task.Dispose();
        }
    }
}
